package net.openadventure.sprites;

import java.awt.Polygon;

import util.OAUtil;
import util.Point;

/**
 * A generic class to display a background-independent image. This is a
 * lightweight information-only class. A Sprite must be passed to the Engine and
 * converted to a ScreenElement before its image is loaded. A Sprite is
 * immutable. Once made, it can not be changed.
 * 
 * @author Paul
 * 
 */
public class Sprite {

	private final String imagePath; // The relative path to the file of the
	// image to

	// display

	private final int x; // The distance from the left of the canvas to paint
	// this

	// sprite

	private final int y; // The distance from the top of the canvas to paint
	// this

	// sprite

	private final Point originalCenter;

	private final Polygon footprint;

	private final int width; // The width of the sprite, in pixels

	private final int height; // The height of the sprite, in pixels

	private boolean flipHorizontal = false; // Keeps track of the image's

	// horizontal flip orientation

	private boolean flipVertical = false; // Keeps track of the image's

	// vertical flip orientation

	/**
	 * Creates a new sprite with the given image and location.
	 * 
	 * @param imagePath
	 *            the relative path to the image to display for this sprite
	 * @param x
	 *            the x-coordinate, in pixels
	 * @param y
	 *            the y-coordinate, in pixels
	 * @param width
	 *            the width of the sprite, in pixels
	 * @param height
	 *            the height of the sprite, in pixels
	 * @throws NullPointerException
	 *             if the imagePath parameter is null
	 * @throws IllegalArgumentException
	 *             if the width parameter is less than 1
	 * @throws IllegalArgumentException
	 *             if the height parameter is less than 1
	 */
	public Sprite(String imagePath, int x, int y, Point originalCenter,
			Polygon footprint, int width, int height, boolean flipHorizontal,
			boolean flipVertical) {
		// Check parameters
		OAUtil.verifyNotNull(imagePath, "imagePath");
		OAUtil.verifyNotLessThanOne(width, "width");
		OAUtil.verifyNotLessThanOne(height, "height");

		this.imagePath = imagePath;
		this.x = x;
		this.y = y;
		this.originalCenter = originalCenter;
		this.footprint = footprint;
		this.width = width;
		this.height = height;
		this.flipHorizontal = flipHorizontal;
		this.flipVertical = flipVertical;

	}

	/**
	 * Gets the relative path to the image displayed by this sprite
	 * 
	 * @return the path
	 */
	public String getImagePath() {
		return imagePath;
	}

	/**
	 * Gets the horizontal flip flag for this sprite. A horizontally flipped
	 * sprite is flipped left to right.
	 * 
	 * @return true = the image will be flipped horizontally; false = the image
	 *         will not be flipped horizontally
	 */
	public boolean getFlipHorizontal() {
		return flipHorizontal;
	}

	/**
	 * Gets the vertical flip flag for this sprite. A vertically flipped sprite
	 * is flipped top to bottom.
	 * 
	 * @return true = the image will be flipped vertically; false = the image
	 *         will be flipped vertically
	 */
	public boolean getFlipVertical() {
		return flipVertical;
	}

	/**
	 * Gets the height of the sprite
	 * 
	 * @return the height, in pixels
	 */
	public int getHeight() {
		return height;
	}

	/**
	 * Gets the width of the sprite
	 * 
	 * @return the width, in pixels
	 */
	public int getWidth() {
		return width;
	}

	/**
	 * Gets the x-coordinate location of the sprite
	 * 
	 * @return the x-coordinate, in pixels
	 */
	public int getX() {
		return x;
	}

	/**
	 * Gets the y-coordinate location of the sprite
	 * 
	 * @return the y-coordinate, in pixels
	 */
	public int getY() {
		return y;
	}

	public Point getOriginalCenter() {
		if (originalCenter != null) {
			return new Point(originalCenter.getX(), originalCenter.getY());
		} else {
			return new Point(0, 0);
		}
	}

	public Point getActualCenter() {
		return new Point(x + originalCenter.getX(), y + originalCenter.getY());
	}

	// Returns the footprint in sprite space
	public Polygon getOriginalFootPrint() {
		if (footprint != null) {
			return new Polygon(footprint.xpoints, footprint.ypoints,
					footprint.npoints);
		} else {
			return null;
		}
	}

	// Returns the footprint in window space
	public Polygon getActualFootPrint() {
		Polygon transFoot = null;
		if (footprint != null) {
			transFoot = new Polygon(footprint.xpoints.clone(),
					footprint.ypoints.clone(), footprint.npoints);
			transFoot.translate(x, y);
		}
		return transFoot;
	}

	@Override
	public String toString() {
		return "Sprite[imagePath=" + imagePath + ",x=" + x + ",y=" + y
				+ ",originalCenter=" + originalCenter + ",footPrint="
				+ footprint + ",width=" + width + ",height=" + height
				+ ",flipHorizontal=" + flipHorizontal + ",flipVertical="
				+ flipVertical + "]";
	}

}
